﻿/*
    Nova Code - A script language, parser and recompiler for implementing emulated code instructions
    Copyright (C) 2012  Bryan Perris

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nova.Parsing.GoldParser.Semantic;

namespace Nova.Parsing.Tokens
{
    [Terminal("||")]
    [Terminal("&&")]
    [Terminal("|")]
    [Terminal("&")]
    [Terminal("^")]
    [Terminal("==")]
    [Terminal("!=")]
    [Terminal("<")]
    [Terminal("<=")]
    [Terminal(">")]
    [Terminal(">=")]
    [Terminal("<<")]
    [Terminal(">>")]
    [Terminal("<<<")]
    [Terminal(">>>")]
    [Terminal("+")]
    [Terminal("-")]
    [Terminal("*")]
    [Terminal("/")]
    [Terminal("%")]
    [Terminal("~")]
    [Terminal("!")]
    [Terminal("--")]
    [Terminal("++")]
    [Terminal("=")]
    [Terminal("+=")]
    [Terminal("-=")]
    [Terminal("*=")]
    [Terminal("/=")]
    [Terminal("&=")]
    [Terminal("|=")]
    [Terminal(">>=")]
    [Terminal(">>>=")]
    [Terminal("<<=")]
    [Terminal("<<<=")]
    [Terminal("^=")]
    public sealed class OperatorToken : NovaToken
    {
        private OperatorType m_OperatorType;
        private static Dictionary<string, OperatorType> s_OperatorLookup = new Dictionary<string,OperatorType>();

        static OperatorToken()
        {
            s_OperatorLookup.Add("||", OperatorType.LogicalOr);
            s_OperatorLookup.Add("&&", OperatorType.LogicalAnd);
            s_OperatorLookup.Add("&", OperatorType.BitwiseAnd);
            s_OperatorLookup.Add("|", OperatorType.BitwiseOr);
            s_OperatorLookup.Add("^", OperatorType.BitwiseXor);
            s_OperatorLookup.Add("==", OperatorType.CompareEquals);
            s_OperatorLookup.Add("!=", OperatorType.CompareNotEquals);
            s_OperatorLookup.Add("<", OperatorType.CompareLessThan);
            s_OperatorLookup.Add("<=", OperatorType.CompareLessThanOrEqual);
            s_OperatorLookup.Add(">", OperatorType.CompareGreaterThan);
            s_OperatorLookup.Add(">=", OperatorType.CompareGreaterThanOrEqual);
            s_OperatorLookup.Add(">>", OperatorType.ShiftRight);
            s_OperatorLookup.Add(">>>", OperatorType.ShiftRightSigned);
            s_OperatorLookup.Add("<<", OperatorType.ShiftLeft);
            s_OperatorLookup.Add("<<<", OperatorType.ShiftLeftSigned);
            s_OperatorLookup.Add("+", OperatorType.Add);
            s_OperatorLookup.Add("-", OperatorType.Subtract);
            s_OperatorLookup.Add("*", OperatorType.Multiply);
            s_OperatorLookup.Add("/", OperatorType.Divide);
            s_OperatorLookup.Add("%", OperatorType.Modulus);
            s_OperatorLookup.Add("~", OperatorType.BitwiseNot);
            s_OperatorLookup.Add("!", OperatorType.BoolNot);
            s_OperatorLookup.Add("--", OperatorType.UnarySubtract);
            s_OperatorLookup.Add("++", OperatorType.UnaryAdd);
            s_OperatorLookup.Add("=", OperatorType.Equals);
            s_OperatorLookup.Add("+=", OperatorType.Add);
            s_OperatorLookup.Add("-=", OperatorType.Subtract);
            s_OperatorLookup.Add("*=", OperatorType.Multiply);
            s_OperatorLookup.Add("/=", OperatorType.Divide);
            s_OperatorLookup.Add("&=", OperatorType.BitwiseAnd);
            s_OperatorLookup.Add("|=", OperatorType.BitwiseOr);
            s_OperatorLookup.Add(">>=", OperatorType.ShiftRight);
            s_OperatorLookup.Add(">>>=", OperatorType.ShiftRightSigned);
            s_OperatorLookup.Add("<<=", OperatorType.ShiftLeft);
            s_OperatorLookup.Add("<<<=", OperatorType.ShiftLeftSigned);
            s_OperatorLookup.Add("^=", OperatorType.BitwiseXor);
        }

        public OperatorToken(string operatorSymbol)
        {
            if (!s_OperatorLookup.TryGetValue(operatorSymbol, out m_OperatorType))
            {
                throw new ArgumentException("Invalid operator token: " + operatorSymbol);
            }
        }

        public OperatorType Operator
        {
            get
            {
                return m_OperatorType;
            }
        }

        public override string ToString()
        {
            return String.Concat("Operator Type: ", Operator.ToString());
        }
    }
}
